/*
 * Copyright (c) 2016. 恒昌互联网运营中心.
 */
package com.credithc.eagleeye.agent.factory;
import com.credithc.eagleeye.agent.IEagleEyeAgent;
import com.credithc.eagleeye.agent.bean.EagleEyeAgentConfig;
import com.credithc.eagleeye.agent.strategy.HttpEagleEyeAgent;
import com.credithc.eagleeye.agent.strategy.RedisEagleEyeAgent;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
 * 描 述: <br/>
 * 作 者: zhangjin<br/>
 * 创 建：2016年09月30日<br/>
 * 版 本：v1.0.0<br>
 * <p/>
 * 历 史: (版本) 作者 时间 注释 <br/>
 */
public class EagleEyeAgentFactory {
    //单例
    private static IEagleEyeAgent instance;
    private transient static final Logger logger = LoggerFactory.getLogger(RedisEagleEyeAgent.class);
    /**
     * 默认配置文件
     */
    protected final static String DEFAULT_PROPERTIES_PATH = "property/eagle-agent-config.properties";
    private static Properties loadProperties(String localPropertiesPath) {
        Properties localProperties = new Properties();
        try (InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream(localPropertiesPath)) {
            if (null == input) {
                //throw new RuntimeException("EagleAgent未找到配置文件:" + localPropertiesPath);
                logger.warn("EagleAgent未找到配置文件:" + localPropertiesPath);
                return null;
            }
            localProperties.load(input);
        } catch (final IOException ex) {
            throw new RuntimeException(ex);
        }
        return localProperties;
    }
    private static EagleEyeAgentConfig fillEagleEyeAgentConfig(Properties properties) {
        EagleEyeAgentConfig eagleEyeAgentConfig = new EagleEyeAgentConfig();
        if (properties != null) {
            // 设置初始值
            String redisAddress = properties.getProperty("eagle.agent.redis.address", "");
            long redisMaxWaitMillis = Long.parseLong(properties.getProperty("eagle.agent.redis.maxWaitMillis", String.valueOf(GenericObjectPoolConfig.DEFAULT_MAX_WAIT_MILLIS)));
            int redisMaxTotal = Integer.parseInt(properties.getProperty("eagle.agent.redis.maxTotal", String.valueOf(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL)));
            int redisMinIdle = Integer.parseInt(properties.getProperty("eagle.agent.redis.minIdle", String.valueOf(GenericObjectPoolConfig.DEFAULT_MIN_IDLE)));
            int redisMaxIdle = Integer.parseInt(properties.getProperty("eagle.agent.redis.maxIdle", String.valueOf(GenericObjectPoolConfig.DEFAULT_MAX_IDLE)));
            int redisTimeout = Integer.parseInt((properties.getProperty("eagle.agent.redis.timeout", "2000")));
            String agentClientName = properties.getProperty("eagle.agent.clientName", "");
            String agentPlatformName = properties.getProperty("eagle.agent.platformName", "");
            String agentEnv = properties.getProperty("eagle.agent.env", "");
            String agentMode = properties.getProperty("eagle.agent.mode", "");
            boolean enableMvcParameter = Boolean.parseBoolean(properties.getProperty("eagle.agent.plugin.enableMvcParameter", "true"));
            boolean enableMybatisSql = Boolean.parseBoolean(properties.getProperty("eagle.agent.plugin.enableMybatisSql", "true"));
            boolean enableMybatisResult = Boolean.parseBoolean(properties.getProperty("eagle.agent.plugin.enableMybatisResult", "true"));
            int mybatisMaxSqlLength = Integer.parseInt((properties.getProperty("eagle.agent.plugin.mybatisMaxSqlLength", "4000")));
            boolean enableMybatisConvertSql = Boolean.parseBoolean(properties.getProperty("eagle.agent.plugin.enableMybatisConvertSql", "true"));
            boolean enablePrintLog = Boolean.parseBoolean(properties.getProperty("eagle.agent.plugin.enablePrintLog", "false"));


            String iceLocator = properties.getProperty("eagle.agent.ice.locator", "");
            int iceLocatorCacheTimeout = Integer.parseInt((properties.getProperty("eagle.agent.ice.locator.cache.timeout", "10")));


            String httpHost=properties.getProperty("eagle.agent.http.host", "");
            String httpPort=properties.getProperty("eagle.agent.http.port", "8080");

            if (agentEnv == null || agentEnv.length() == 0) {
                throw new RuntimeException("EagleAgent error:eagle.agent.env is blank!");
            }
            if (agentClientName == null || agentClientName.length() == 0) {
                throw new RuntimeException("EagleAgent error:eagle.agent.clientName is blank!");
            }
            if (agentPlatformName == null || agentPlatformName.length() == 0) {
                throw new RuntimeException("EagleAgent error:eagle.agent.platformName is blank!");
            }
            if (agentMode == null || agentMode.length() == 0) {
                throw new RuntimeException("EagleAgent error:eagle.agent.mode is blank!");
            } else {
                if (agentMode.equalsIgnoreCase("ice")) {
                    if (iceLocator == null || iceLocator.length() == 0) {
                        throw new RuntimeException("EagleAgent error:eagle.agent.mode=ice, but iceLocator is blank!");
                    }
                } else if (agentMode.equalsIgnoreCase("redis")) {
                    if (redisAddress == null || redisAddress.length() == 0) {
                        throw new RuntimeException("EagleAgent error:eagle.agent.mode=redis, but redisAddress is blank!");
                    }
                }else if (agentMode.equalsIgnoreCase("http")) {
                    if (httpHost == null || httpHost.length() == 0) {
                        throw new RuntimeException("EagleAgent error:eagle.agent.mode=http, but httpHost is blank!");
                    }
                }
            }
            eagleEyeAgentConfig.setAgentEnv(agentEnv);
            eagleEyeAgentConfig.setAgentClientName(agentClientName);
            eagleEyeAgentConfig.setAgentMode(agentMode);
            eagleEyeAgentConfig.setAgentPlatform(agentPlatformName);
            eagleEyeAgentConfig.setRedisAddress(redisAddress);
            eagleEyeAgentConfig.setRedisMaxIdle(redisMaxIdle);
            eagleEyeAgentConfig.setRedisMaxTotal(redisMaxTotal);
            eagleEyeAgentConfig.setRedisMinIdle(redisMinIdle);
            eagleEyeAgentConfig.setRedisTimeout(redisTimeout);
            eagleEyeAgentConfig.setRedisMaxWaitMillis(redisMaxWaitMillis);
            eagleEyeAgentConfig.setIceLocator(iceLocator);
            eagleEyeAgentConfig.setIceLocatorCacheTimeout(iceLocatorCacheTimeout);
            eagleEyeAgentConfig.setHttpHost(httpHost);
            eagleEyeAgentConfig.setHttpPort(httpPort);
            eagleEyeAgentConfig.setEnableMvcParameter(enableMvcParameter);
            eagleEyeAgentConfig.setEnableMybatisSql(enableMybatisSql);
            eagleEyeAgentConfig.setEnableMybatisResult(enableMybatisResult);
            eagleEyeAgentConfig.setMybatisMaxSqlLength(mybatisMaxSqlLength);
            eagleEyeAgentConfig.setEnableMybatisConvertSql(enableMybatisConvertSql);
            eagleEyeAgentConfig.setEnablePrintLog(enablePrintLog);

        }
        return eagleEyeAgentConfig;
    }
    public static IEagleEyeAgent getInstance() {
        if (instance == null) {
            createInstance(DEFAULT_PROPERTIES_PATH);
        }
        return instance;
    }
    public static IEagleEyeAgent createInstance(String localPropertiesPath) {
        if (instance == null) {
            synchronized (EagleEyeAgentFactory.class) {
                if (instance == null) {
                    logger.info("EagleEyeAgent starting... init properties path:" + localPropertiesPath);
                    Properties localProperties = loadProperties(localPropertiesPath);
                    EagleEyeAgentConfig eagleEyeAgentConfig = fillEagleEyeAgentConfig(localProperties);
                    return createInstance(eagleEyeAgentConfig);
                }
            }
        }
        return instance;
    }

    public static IEagleEyeAgent createInstance(EagleEyeAgentConfig eagleEyeAgentConfig) {
        if (instance == null) {
            synchronized (EagleEyeAgentFactory.class) {
                if (instance == null) {
                    switch (eagleEyeAgentConfig.getAgentMode()) {
                        case "redis":
                            instance = new RedisEagleEyeAgent(eagleEyeAgentConfig);
                            break;
                        case "ice":
                            //instance = new IceEagleEyeAgent(eagleEyeAgentConfig);
                            throw new RuntimeException("EagleAgent ice 模式已被遗弃，请选择其他接口方式！");
                        case "http":
                            instance = new HttpEagleEyeAgent(eagleEyeAgentConfig);
                            break;
                        default:
                            throw new RuntimeException("Unknown EagleAgent mode: " + eagleEyeAgentConfig.getAgentMode());
                    }
                }
            }
        }
        return instance;
    }
}
